import json
import re

from django.contrib.auth import authenticate, login
# Create your views here.
from django.db import transaction
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_jwt.settings import api_settings

from users.models import User
from users.serializers import UserSerializer
from utils.response.response import ReturnMsg


class LoginView(APIView):
    permission_classes = [AllowAny]

    def post(self, request):
        # 登陆
        data = request.data
        username = data.get("username")
        password = data.get("password")
        # 2.校验(整体 + 单个)
        if not all([username, password]):
            return Response(ReturnMsg(code=0, msg="错误", errors="用户名或密码未提供").dict())
        # 修改 USERNAME_FIELD 来影响 authenticate 的查询
        if re.match(r"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$", username):
            # 邮箱
            User.USERNAME_FIELD = "email"
        else:
            # account 是用户名
            # 根据用户名从数据库获取 user 对象返回.
            User.USERNAME_FIELD = "username"
        # 3.验证是否能够登录
        user = authenticate(username=username,
                            password=password)
        # 判断是否为空,如果为空,返回
        if user is None:
            return Response(ReturnMsg(code=0, msg="错误", errors="用户名或密码错误").dict())
        # 生成token，并返回给前端
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        return Response(ReturnMsg(code=1, msg="访问成功", data={
            "username": user.username,
            "token": token
        }).dict())


class RegisterView(APIView):
    permission_classes = [AllowAny]

    def post(self, request):
        data = request.data
        username = data.get('username')
        password = data.get('password')
        password2 = data.get('password2')

        if not all([username, password, password2, ]):
            return Response(ReturnMsg(code=0, msg="错误", errors="参数未完全提供").dict())
        # 判断用户名是否是5-20个字符
        if not re.match(r'^\w{5,20}$', username):
            return Response(ReturnMsg(code=0, msg="错误", errors="用户名必须为5-20个字符").dict())

        # 判断密码是否是5-17个数字
        if not re.match(r'^[a-zA-Z]\w{5,17}$', password):
            return Response(ReturnMsg(code=0, msg="错误", errors="密码必须以字母开头，长度在6~18之间，只能包含字母、数字和下划线").dict())
        # 判断两次密码是否一致
        if password != password2:
            return Response(ReturnMsg(code=0, msg="错误", errors="两次密码输入不一致").dict())
        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            user = None

        if user is not None:
            return Response(ReturnMsg(code=0, msg="错误", errors="用户名已被注册").dict())
        try:
            user = User.objects.create_user(username=username,
                                            password=password,
                                            )
        except:
            return Response(ReturnMsg(code=0, msg="错误", errors="注册账号失败").dict())

        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        return Response(ReturnMsg(code=1, msg="访问成功", data={
            "username": user.username,
            "token": token
        }).dict())


class SubmitView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        data = request.data
        # 从form表单获取数据
        avatar = data.get('avatar')
        name = data.get('name')
        telephone = data.get('telephone')
        birthday = data.get('date')
        text = data.get('text')
        sex = data.get('sex')

        # 判断参数是否齐全
        if not all([name, birthday, text, sex]):
            return Response(ReturnMsg(code=0, msg="错误", errors="缺少必传参数").dict())
        # 判断用户名是否是5-20个字符
        if sex not in ['男', '女']:
            return Response(ReturnMsg(code=0, msg="错误", errors="性别输入有误").dict())
        import datetime
        try:
            birthday = datetime.datetime.strptime(birthday, "%Y-%m-%d").date()
        except:
            return Response(ReturnMsg(code=0, msg="错误", errors="生日输入有误").dict())
        try:
            with transaction.atomic():
                savepoint = transaction.savepoint()
                # 数据保存
                request.user.avatar = avatar
                request.user.birthday = birthday
                request.user.name = name
                request.user.sex = sex
                request.user.text = text
                request.user.telephone = telephone
                request.user.save()
        except:
            transaction.savepoint_rollback(savepoint)
            return Response(ReturnMsg(code=0, msg="错误", errors="提交失败").dict())
        return Response(ReturnMsg(code=1, msg="提交成功", data=UserSerializer(self.request.user).data).dict())


class GetInfoView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user
        return Response(ReturnMsg(code=1, msg="获取成功", data=UserSerializer(user).data).dict())


class UpDateView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        user = request.user
        data = request.data
        # print(data)
        try:
            if data.get('avatar'):
                user.avatar = data.get('avatar')
            user.text = data.get('text')
            user.name = data.get('name')
            user.birthday = data.get('birthday')
            user.telephone = data.get('telephone')
            user.save()
        except:
            return Response(ReturnMsg(code=0, msg="失败", errors="操作错误").dict())

        return Response(ReturnMsg(code=1, msg="修改成功", data=UserSerializer(user).data).dict())

